// service/vote_service.go
package service

import (
	"context"
	"fmt"
	"sort"
	"sync"

	//"sync/atomic"

	//"sync/atomic"

	"vote-service/gen/vote"
	"vote-service/gen/vote/voteconnect"

	//"github.com/connectrpc/connect-go"
	"connectrpc.com/connect"
)

type VoteService struct {
	mu      sync.RWMutex
	options map[string]*vote.Option
	topic   string
}

/*
主要区别
特性	sync.Mutex (普通互斥锁)	sync.RWMutex (读写互斥锁)
锁类型	独占锁	读写分离锁
读操作	互斥，只能一个goroutine访问	共享，多个goroutine可同时读
写操作	互斥，只能一个goroutine访问	互斥，只能一个goroutine写
性能	较低	较高（读多写少场景）
使用场景	读写都少的场景	读多写少的场景
*/
// type VoteService struct {
// 	mu          sync.RWMutex
// 	options     map[string]*vote.Option
// 	votes       map[string]int32
// 	topic       string
// 	sortedCache []*vote.Option // 缓存排序后的结果
// 	dirty       bool           // 标记缓存是否过期
// 	cacheHits   int64          // 添加缓存命中计数器
// 	cacheMisses int64          // 添加缓存未命中计数器
// }

func NewVoteService() *VoteService {
	// 初始化固定的投票主题和选项
	options := map[string]*vote.Option{
		"1": {Id: "1", Text: "选项A: Go", Votes: 0},
		"2": {Id: "2", Text: "选项B: Python", Votes: 0},
		"3": {Id: "3", Text: "选项C: Java", Votes: 0},
		"4": {Id: "4", Text: "选项D: JavaScript", Votes: 0},
	}

	return &VoteService{
		options: options,
		topic:   "你最喜欢的编程语言是什么？",
	}
}

func (s *VoteService) Vote(
	ctx context.Context,
	req *connect.Request[vote.VoteRequest],
) (*connect.Response[vote.VoteResponse], error) {
	s.mu.Lock()
	defer s.mu.Unlock()
	/*
			特性	s.mu.RLock() (读锁)	s.mu.Lock() (写锁)
		锁类型	共享锁	独占锁
		并发性	多个 goroutine 可同时获取	只能一个 goroutine 获取
		阻塞情况	不阻塞其他读锁，阻塞写锁	阻塞所有其他锁
		使用场景	只读操作	写入操作
	*/
	optionID := req.Msg.OptionId
	option, exists := s.options[optionID]
	if !exists {
		return nil, connect.NewError(connect.CodeNotFound,
			fmt.Errorf("选项 %s 不存在", optionID))
	}

	option.Votes++

	response := &vote.VoteResponse{
		Success: true,
		Message: fmt.Sprintf("成功为 %s 投票", option.Text),
	}
	//s.dirty = true // 标记缓存过期
	return connect.NewResponse(response), nil
}

func (s *VoteService) GetResults(
	ctx context.Context,
	req *connect.Request[vote.GetResultsRequest],
) (*connect.Response[vote.GetResultsResponse], error) {
	s.mu.RLock()         //在函数开始时调用，立即获取读锁。
	defer s.mu.RUnlock() // 释放，用defer好. 将解锁操作延迟到函数返回前执行，确保在函数执行过程中数据的一致性。
	// if !s.dirty && s.sortedCache != nil {
	// 	// 缓存命中
	// 	atomic.AddInt64(&s.cacheHits, 1)
	// 	log.Printf("缓存命中! 总命中次数: %d", atomic.LoadInt64(&s.cacheHits))
	// 	// 返回缓存结果（无锁，极快）
	// 	response := &vote.GetResultsResponse{
	// 		Topic:   s.topic,
	// 		Options: s.sortedCache,
	// 	}
	// 	s.mu.RUnlock()
	// 	return connect.NewResponse(response), nil
	// }

	//s.mu.RUnlock()
	// 缓存未命中
	//atomic.AddInt64(&s.cacheMisses, 1)
	//log.Printf("缓存未命中! 正在重建缓存... 总未命中次数: %d", atomic.LoadInt64(&cacheMisses))
	// 需要重新构建缓存
	// s.mu.Lock()
	// defer s.mu.Unlock()
	options := make([]*vote.Option, 0, len(s.options))
	for _, option := range s.options {
		options = append(options, &vote.Option{
			Id:    option.Id,
			Text:  option.Text,
			Votes: option.Votes,
		})
	}

	// 服务端排序（低开销）
	sort.Slice(options, func(i, j int) bool {
		return options[i].Id < options[j].Id // 按ID排序
	})
	/*ids := []string{"1", "2", "3", "4"} // 按顺序添加

	for _, id := range ids {
		if option, exists := s.options[id]; exists {
			options = append(options, &vote.Option{
				Id:    option.Id,
				Text:  option.Text,
				Votes: option.Votes,
			})
		}
	}  这个是对少量的id 排序*/
	/*for _, option := range s.options {
		options = append(options, &vote.Option{
			Id:    option.Id,
			Text:  option.Text,
			Votes: option.Votes,
		})
	}      这个将返回无序的选项*/
	// s.sortedCache = options
	// s.dirty = false
	//log.Printf("缓存重建完成! 缓存大小: %d 个选项", len(options))
	response := &vote.GetResultsResponse{
		Topic:   s.topic,
		Options: options,
	}

	return connect.NewResponse(response), nil
}

// 添加监控端点
// 在 VoteService 中添加
// func (s *VoteService) GetCacheStats(ctx context.Context, req *connect.Request[votingv1.GetStatsRequest]) (*connect.Response[votingv1.GetStatsResponse], error) {
// 	hits, misses := atomic.LoadInt64(&s.cacheHits), atomic.LoadInt64(&s.cacheMisses)
// 	hitRate := 0.0
// 	if hits+misses > 0 {
// 		hitRate = float64(hits) / float64(hits+misses) * 100
// 	}

// 	response := &votingv1.GetStatsResponse{
// 		CacheHits:   hits,
// 		CacheMisses: misses,
// 		HitRate:     hitRate,
// 		CacheSize:   int32(len(s.sortedCache)),
// 		IsDirty:     s.dirty,
// 	}

// 	return connect.NewResponse(response), nil
// }

// 实现 Connect 服务接口
func (s *VoteService) ServiceName() string {
	return voteconnect.VoteServiceName
}
